import React, { useMemo, AnchorHTMLAttributes, ButtonHTMLAttributes, ReactNode, PropsWithChildren } from "react";
import styled from "styled-components";
import { color, typography } from "../shared/styles";
import { darken, rgba, opacify } from "polished";
import {easing}from '../shared/animation'


/* type */
export type AppearancesTypes = keyof typeof APPEARANCES;

type btnType =
	| "primary"
	| "primaryOutline"
	| "secondary"
	| "secondaryOutline"
	| "tertiary"
	| "outline"
	| "inversePrimary"
	| "inverseSecondary"
	| "inverseOutline";

type AppearancesObj = {
	[key in btnType]: btnType;
};

export const APPEARANCES: AppearancesObj = {
	primary: "primary",
	primaryOutline: "primaryOutline",
	secondary: "secondary",
	secondaryOutline: "secondaryOutline",
	tertiary: "tertiary",
	outline: "outline",
	inversePrimary: "inversePrimary",
	inverseSecondary: "inverseSecondary",
	inverseOutline: "inverseOutline",
};

/* size */
export type SizesTypes = keyof typeof SIZES;
type sizeType = "small" | "medium";
type sizeObj = {
	[key in sizeType]: sizeType;
};
export const SIZES: sizeObj = {
	small: "small",
	medium: "medium",
};
// export type SizesTypes=keyof typeof SIZES

// const SIZES = {
//     small: 'small',
//     medium: 'medium',
// };

/* text & loading */
const Text = styled.span`
	display: inline-block;
	vertical-align: top;
`;

const Loading = styled.span`
	position: absolute;
	top: 50%;
	left: 0;
	right: 0;
	opacity: 0;
`;

/* interface */
export interface CustormButtonProps {
	/** 是否禁用 */
	disabled?: boolean;
	/** 是否加载中 */
	isLoading?: boolean;
	/** 是否是a标签 */
	isLink?: boolean;
	/** 是否替换加载中文本 */
	loadingText?: ReactNode;
	/** 按钮大小 */
	size?: SizesTypes;
	/** 按钮类型 */
	appearance?: AppearancesTypes;
	/** 无效点击 */
	isUnclickable?: boolean;
}

export type ButtonProps = CustormButtonProps &
	AnchorHTMLAttributes<HTMLAnchorElement> &
    ButtonHTMLAttributes<HTMLButtonElement>;
    

/* styles */
const StyledButton = styled.button<ButtonProps>`
  border: 0;
  border-radius: 3em;
  cursor: pointer;
  display: inline-block;
  overflow: hidden;
  padding: ${(props) =>
		props.size === SIZES.small ? "8px 16px" : "13px 20px"};
  position: relative;
  text-align: center;
  text-decoration: none;
  transition: all 150ms ease-out;
  transform: translate3d(0,0,0);
  vertical-align: top;
  white-space: nowrap;
  user-select: none;
  opacity: 1;
  margin: 0;
  background: transparent;


  font-size: ${(props) =>
		props.size === SIZES.small ? typography.size.s1 : typography.size.s2}px;
  font-weight: ${typography.weight.extrabold};
  line-height: 1;

  ${(props) =>
		!props.isLoading &&
		`
      &:hover {
        transform: translate3d(0, -2px, 0);
        box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0;
      }

      &:active {
        transform: translate3d(0, 0, 0);
      }

      &:focus {
        box-shadow: ${rgba(color.primary, 0.4)} 0 1px 9px 2px;
      }

      &:focus:hover {
        box-shadow: ${rgba(color.primary, 0.2)} 0 8px 18px 0px;
      }
    `}

  ${Text} {
    transform: scale3d(1,1,1) translate3d(0,0,0);
    transition: transform 700ms ${easing.rubber};
    opacity: 1;
  }

  ${Loading} {
    transform: translate3d(0, 100%, 0);
  }

  ${(props) =>
		props.disabled &&
		`
      cursor: not-allowed !important;
      opacity: 0.5;
      &:hover {
        transform: none;
      }
    `}

  ${(props) =>
		props.isUnclickable &&
		`
      cursor: default !important;
      pointer-events: none;
      &:hover {
        transform: none;
      }
    `}

  ${(props) =>
		props.isLoading &&
		`
      cursor: progress !important;
      opacity: 0.7;

      ${Loading} {
        transition: transform 700ms ${easing.rubber};
        transform: translate3d(0, -50%, 0);
        opacity: 1;
      }

      ${Text} {
        transform: scale3d(0, 0, 1) translate3d(0, -100%, 0);
        opacity: 0;
      }

      &:hover {
        transform: none;
      }
    `}



  ${(props) =>
		props.appearance === APPEARANCES.primary &&
		`
      background: ${color.primary};
      color: ${color.lightest};

      ${!props.isLoading &&
			`
          &:hover {
            background: ${darken(0.05, color.primary)};
          }
          &:active {
            box-shadow: rgba(0, 0, 0, 0.1) 0 0 0 3em inset;
          }
          &:focus {
            box-shadow: ${rgba(color.primary, 0.4)} 0 1px 9px 2px;
          }
          &:focus:hover {
            box-shadow: ${rgba(color.primary, 0.2)} 0 8px 18px 0px;
          }
        `}
    `}

  ${(props) =>
		props.appearance === APPEARANCES.secondary &&
		`
      background: ${color.secondary};
      color: ${color.lightest};

      ${!props.isLoading &&
			`
          &:hover {
            background: ${darken(0.05, color.secondary)};
          }
          &:active {
            box-shadow: rgba(0, 0, 0, 0.1) 0 0 0 3em inset;
          }
          &:focus {
            box-shadow: ${rgba(color.secondary, 0.4)} 0 1px 9px 2px;
          }
          &:focus:hover {
            box-shadow: ${rgba(color.secondary, 0.2)} 0 8px 18px 0px;
          }
        `}
    `}

  ${(props) =>
		props.appearance === APPEARANCES.tertiary &&
		`
      background: ${color.tertiary};
      color: ${color.darkest};

      ${!props.isLoading &&
			`
          &:hover {
            background: ${darken(0.05, color.tertiary)};
          }
          &:active {
            box-shadow: rgba(0, 0, 0, 0.1) 0 0 0 3em inset;
          }
          &:focus {
            box-shadow: ${rgba(color.darkest, 0.15)} 0 1px 9px 2px;
          }
          &:focus:hover {
            box-shadow: ${rgba(color.darkest, 0.05)} 0 8px 18px 0px;
          }
        `}
    `}

  ${(props) =>
		props.appearance === APPEARANCES.outline &&
		`
      box-shadow: ${opacify(0.05, color.border)} 0 0 0 1px inset;
      color: ${color.dark};
      background: transparent;

      ${!props.isLoading &&
			`
          &:hover {
            box-shadow: ${opacify(0.3, color.border)} 0 0 0 1px inset;
          }

          &:active {
            background: ${opacify(0.05, color.border)};
            box-shadow: transparent 0 0 0 1px inset;
            color: ${color.darkest};
          }

          &:active:focus:hover {
            ${
				/* This prevents the semi-transparent border from appearing atop the background */ ""
			}
            background: ${opacify(0.05, color.border)};
            box-shadow:  ${rgba(color.darkest, 0.15)} 0 1px 9px 2px;
          }

          &:focus {
            box-shadow: ${opacify(0.05, color.border)} 0 0 0 1px inset, 
            ${rgba(color.darkest, 0.15)} 0 1px 9px 2px;
          }
          &:focus:hover {
            box-shadow: ${opacify(0.05, color.border)} 0 0 0 1px inset, 
            ${rgba(color.darkest, 0.05)} 0 8px 18px 0px;
          }
        `};
    `};

    ${(props) =>
		props.appearance === APPEARANCES.primaryOutline &&
		`
        box-shadow: ${color.primary} 0 0 0 1px inset;
        color: ${color.primary};

        &:hover {
          box-shadow: ${color.primary} 0 0 0 1px inset;
          background: transparent;
        }

        &:active {
          background: ${color.primary};
          box-shadow: ${color.primary} 0 0 0 1px inset;
          color: ${color.lightest};
        }
        &:focus {
          box-shadow: ${color.primary} 0 0 0 1px inset, ${rgba(
			color.primary,
			0.4
		)} 0 1px 9px 2px;
        }
        &:focus:hover {
          box-shadow: ${color.primary} 0 0 0 1px inset, ${rgba(
			color.primary,
			0.2
		)} 0 8px 18px 0px;
        }
      `};

    ${(props) =>
		props.appearance === APPEARANCES.secondaryOutline &&
		`
        box-shadow: ${color.secondary} 0 0 0 1px inset;
        color: ${color.secondary};

        &:hover {
          box-shadow: ${color.secondary} 0 0 0 1px inset;
          background: transparent;
        }

        &:active {
          background: ${color.secondary};
          box-shadow: ${color.secondary} 0 0 0 1px inset;
          color: ${color.lightest};
        }
        &:focus {
          box-shadow: ${color.secondary} 0 0 0 1px inset,
            ${rgba(color.secondary, 0.4)} 0 1px 9px 2px;
        }
        &:focus:hover {
          box-shadow: ${color.secondary} 0 0 0 1px inset,
            ${rgba(color.secondary, 0.2)} 0 8px 18px 0px;
        }
      `};

      ${(props) =>
			props.appearance === APPEARANCES.inversePrimary &&
			`
          background: ${color.lightest};
          color: ${color.primary};

          ${!props.isLoading &&
				`
              &:hover {
                background: ${color.lightest};
              }
              &:active {
                box-shadow: rgba(0, 0, 0, 0.1) 0 0 0 3em inset;
              }
              &:focus {
                box-shadow: ${rgba(color.primary, 0.4)} 0 1px 9px 2px;
              }
              &:focus:hover {
                box-shadow: ${rgba(color.primary, 0.2)} 0 8px 18px 0px;
              }
          `}
      `}

      ${(props) =>
			props.appearance === APPEARANCES.inverseSecondary &&
			`
          background: ${color.lightest};
          color: ${color.secondary};

          ${!props.isLoading &&
				`
              &:hover {
                background: ${color.lightest};
              }
              &:active {
                box-shadow: rgba(0, 0, 0, 0.1) 0 0 0 3em inset;
              }
              &:focus {
                box-shadow: ${rgba(color.secondary, 0.4)} 0 1px 9px 2px;
              }
              &:focus:hover {
                box-shadow: ${rgba(color.secondary, 0.2)} 0 8px 18px 0px;
              }
          `}
      `}

      ${(props) =>
			props.appearance === APPEARANCES.inverseOutline &&
			`
          box-shadow: ${color.lightest} 0 0 0 1px inset;
          color: ${color.lightest};

          &:hover {
            box-shadow: ${color.lightest} 0 0 0 1px inset;
            background: transparent;
          }

          &:active {
            background: ${color.lightest};
            box-shadow: ${color.lightest} 0 0 0 1px inset;
            color: ${color.darkest};
          }
          &:focus {
            box-shadow: ${color.lightest} 0 0 0 1px inset,
              ${rgba(color.darkest, 0.4)} 0 1px 9px 2px;
          }
          &:focus:hover {
            box-shadow: ${color.lightest} 0 0 0 1px inset,
              ${rgba(color.darkest, 0.2)} 0 8px 18px 0px;
          }
      `};

`;

function Button(props: PropsWithChildren<ButtonProps>) {
	const { isLoading, loadingText, isLink, children } = props;
	const buttonInner = (
		<>
			<Text>{children}</Text>
			{isLoading && <Loading>{loadingText || "Loading..."}</Loading>}
		</>
	);
	const btnType = useMemo(() => {
		if (isLink) {
			return "a";
		}
	}, [isLink]);

	return (
		<StyledButton as={btnType} {...props}>
			{buttonInner}
		</StyledButton>
	);
}

Button.defaultProps = {
	isLoading: false,
	loadingText: null,
	isLink: false,
	appearance: APPEARANCES.tertiary,
	isDisabled: false,
	isUnclickable: false,
	containsIcon: false,
	size: SIZES.medium,
	ButtonWrapper: undefined,
};

export default Button;